annotate src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @ 1842:6e0aac35bfa9

6980838: G1: guarantee(false) failed: thread has an unexpected active value in its SATB queue Summary: Under certain circumstances a safepoint could happen between a JavaThread object being created and that object being added to the Java threads list. This could cause the active field of that thread's SATB queue to get out-of-sync with respect to the other Java threads. The solution is to activate the SATB queue, when necessary, before adding the thread to the Java threads list, not when the JavaThread object is created. The changeset also includes a small fix to rename the surrogate locker thread from "Surrogate Locker Thread (CMS)" to "Surrogate Locker Thread (Concurrent GC)" since it's also used in G1. Reviewed-by: iveresov, ysr, johnc, jcoomes
author tonyp
date Fri, 01 Oct 2010 16:43:05 -0400
parents e9ff18c4ace7
children f95d63e2154a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1
a61af66fc99e Initial load
duke
parents:
diff changeset
2 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 628
diff changeset
3 * Copyright (c) 2006, 2009, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
5 *
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
8 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
9 *
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
14 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
15 *
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
19 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 628
diff changeset
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 628
diff changeset
21 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 628
diff changeset
22 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
23 *
a61af66fc99e Initial load
duke
parents:
diff changeset
24 */
a61af66fc99e Initial load
duke
parents:
diff changeset
25
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27 # include "incls/_mutableNUMASpace.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
28
a61af66fc99e Initial load
duke
parents:
diff changeset
29
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
30 MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
31 _lgrp_spaces = new (ResourceObj::C_HEAP) GrowableArray<LGRPSpace*>(0, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
32 _page_size = os::vm_page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
33 _adaptation_cycles = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
34 _samples_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
35 update_layout(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
36 }
a61af66fc99e Initial load
duke
parents:
diff changeset
37
a61af66fc99e Initial load
duke
parents:
diff changeset
38 MutableNUMASpace::~MutableNUMASpace() {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
40 delete lgrp_spaces()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
41 }
a61af66fc99e Initial load
duke
parents:
diff changeset
42 delete lgrp_spaces();
a61af66fc99e Initial load
duke
parents:
diff changeset
43 }
a61af66fc99e Initial load
duke
parents:
diff changeset
44
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
45 #ifndef PRODUCT
0
a61af66fc99e Initial load
duke
parents:
diff changeset
46 void MutableNUMASpace::mangle_unused_area() {
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
47 // This method should do nothing.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
48 // It can be called on a numa space during a full compaction.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
49 }
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
50 void MutableNUMASpace::mangle_unused_area_complete() {
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
51 // This method should do nothing.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
52 // It can be called on a numa space during a full compaction.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
53 }
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
54 void MutableNUMASpace::mangle_region(MemRegion mr) {
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
55 // This method should do nothing because numa spaces are not mangled.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
56 }
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
57 void MutableNUMASpace::set_top_for_allocations(HeapWord* v) {
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
58 assert(false, "Do not mangle MutableNUMASpace's");
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
59 }
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
60 void MutableNUMASpace::set_top_for_allocations() {
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
61 // This method should do nothing.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
62 }
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
63 void MutableNUMASpace::check_mangled_unused_area(HeapWord* limit) {
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
64 // This method should do nothing.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
65 }
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
66 void MutableNUMASpace::check_mangled_unused_area_complete() {
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
67 // This method should do nothing.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
68 }
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
69 #endif // NOT_PRODUCT
0
a61af66fc99e Initial load
duke
parents:
diff changeset
70
a61af66fc99e Initial load
duke
parents:
diff changeset
71 // There may be unallocated holes in the middle chunks
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // that should be filled with dead objects to ensure parseability.
a61af66fc99e Initial load
duke
parents:
diff changeset
73 void MutableNUMASpace::ensure_parsability() {
a61af66fc99e Initial load
duke
parents:
diff changeset
74 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
75 LGRPSpace *ls = lgrp_spaces()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
76 MutableSpace *s = ls->space();
605
98cb887364d3 6810672: Comment typos
twisti
parents: 535
diff changeset
77 if (s->top() < top()) { // For all spaces preceding the one containing top()
0
a61af66fc99e Initial load
duke
parents:
diff changeset
78 if (s->free_in_words() > 0) {
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
79 size_t area_touched_words = pointer_delta(s->end(), s->top());
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 462
diff changeset
80 CollectedHeap::fill_with_object(s->top(), area_touched_words);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
81 #ifndef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
82 if (!ZapUnusedHeapArea) {
a61af66fc99e Initial load
duke
parents:
diff changeset
83 area_touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
a61af66fc99e Initial load
duke
parents:
diff changeset
84 area_touched_words);
a61af66fc99e Initial load
duke
parents:
diff changeset
85 }
a61af66fc99e Initial load
duke
parents:
diff changeset
86 #endif
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
87 if (!os::numa_has_static_binding()) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
88 MemRegion invalid;
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
89 HeapWord *crossing_start = (HeapWord*)round_to((intptr_t)s->top(), os::vm_page_size());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
90 HeapWord *crossing_end = (HeapWord*)round_to((intptr_t)(s->top() + area_touched_words),
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
91 os::vm_page_size());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
92 if (crossing_start != crossing_end) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
93 // If object header crossed a small page boundary we mark the area
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
94 // as invalid rounding it to a page_size().
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
95 HeapWord *start = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
96 HeapWord *end = MIN2((HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), page_size()),
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
97 s->end());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
98 invalid = MemRegion(start, end);
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
99 }
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
100
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
101 ls->add_invalid_region(invalid);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103 }
a61af66fc99e Initial load
duke
parents:
diff changeset
104 } else {
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
105 if (!os::numa_has_static_binding()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
106 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
107 MemRegion invalid(s->top(), s->end());
a61af66fc99e Initial load
duke
parents:
diff changeset
108 ls->add_invalid_region(invalid);
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
109 #else
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
110 if (ZapUnusedHeapArea) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
111 MemRegion invalid(s->top(), s->end());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
112 ls->add_invalid_region(invalid);
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
113 } else {
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
114 return;
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
115 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
116 #endif
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
117 } else {
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
118 return;
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
119 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
120 }
a61af66fc99e Initial load
duke
parents:
diff changeset
121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
123
a61af66fc99e Initial load
duke
parents:
diff changeset
124 size_t MutableNUMASpace::used_in_words() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 size_t s = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
126 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
127 s += lgrp_spaces()->at(i)->space()->used_in_words();
a61af66fc99e Initial load
duke
parents:
diff changeset
128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
129 return s;
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131
a61af66fc99e Initial load
duke
parents:
diff changeset
132 size_t MutableNUMASpace::free_in_words() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 size_t s = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
134 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
135 s += lgrp_spaces()->at(i)->space()->free_in_words();
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137 return s;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139
a61af66fc99e Initial load
duke
parents:
diff changeset
140
a61af66fc99e Initial load
duke
parents:
diff changeset
141 size_t MutableNUMASpace::tlab_capacity(Thread *thr) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
142 guarantee(thr != NULL, "No thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
143 int lgrp_id = thr->lgrp_id();
268
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
144 if (lgrp_id == -1) {
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
145 // This case can occur after the topology of the system has
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
146 // changed. Thread can change their location, the new home
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
147 // group will be determined during the first allocation
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
148 // attempt. For now we can safely assume that all spaces
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
149 // have equal size because the whole space will be reinitialized.
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
150 if (lgrp_spaces()->length() > 0) {
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
151 return capacity_in_bytes() / lgrp_spaces()->length();
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
152 } else {
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
153 assert(false, "There should be at least one locality group");
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
154 return 0;
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
155 }
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
156 }
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
157 // That's the normal case, where we know the locality group of the thread.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
158 int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
a61af66fc99e Initial load
duke
parents:
diff changeset
159 if (i == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
162 return lgrp_spaces()->at(i)->space()->capacity_in_bytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
164
a61af66fc99e Initial load
duke
parents:
diff changeset
165 size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const {
268
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
166 // Please see the comments for tlab_capacity().
0
a61af66fc99e Initial load
duke
parents:
diff changeset
167 guarantee(thr != NULL, "No thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
168 int lgrp_id = thr->lgrp_id();
268
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
169 if (lgrp_id == -1) {
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
170 if (lgrp_spaces()->length() > 0) {
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
171 return free_in_bytes() / lgrp_spaces()->length();
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
172 } else {
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
173 assert(false, "There should be at least one locality group");
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
174 return 0;
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
175 }
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
176 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
177 int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
a61af66fc99e Initial load
duke
parents:
diff changeset
178 if (i == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
179 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
181 return lgrp_spaces()->at(i)->space()->free_in_bytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
182 }
a61af66fc99e Initial load
duke
parents:
diff changeset
183
373
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
184
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
185 size_t MutableNUMASpace::capacity_in_words(Thread* thr) const {
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
186 guarantee(thr != NULL, "No thread");
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
187 int lgrp_id = thr->lgrp_id();
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
188 if (lgrp_id == -1) {
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
189 if (lgrp_spaces()->length() > 0) {
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
190 return capacity_in_words() / lgrp_spaces()->length();
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
191 } else {
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
192 assert(false, "There should be at least one locality group");
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
193 return 0;
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
194 }
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
195 }
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
196 int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
197 if (i == -1) {
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
198 return 0;
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
199 }
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
200 return lgrp_spaces()->at(i)->space()->capacity_in_words();
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
201 }
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
202
0
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // Check if the NUMA topology has changed. Add and remove spaces if needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // The update can be forced by setting the force parameter equal to true.
a61af66fc99e Initial load
duke
parents:
diff changeset
205 bool MutableNUMASpace::update_layout(bool force) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 // Check if the topology had changed.
a61af66fc99e Initial load
duke
parents:
diff changeset
207 bool changed = os::numa_topology_changed();
a61af66fc99e Initial load
duke
parents:
diff changeset
208 if (force || changed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // Compute lgrp intersection. Add/remove spaces.
a61af66fc99e Initial load
duke
parents:
diff changeset
210 int lgrp_limit = (int)os::numa_get_groups_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
211 int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
212 int lgrp_num = (int)os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
213 assert(lgrp_num > 0, "There should be at least one locality group");
a61af66fc99e Initial load
duke
parents:
diff changeset
214 // Add new spaces for the new nodes
a61af66fc99e Initial load
duke
parents:
diff changeset
215 for (int i = 0; i < lgrp_num; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
216 bool found = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
217 for (int j = 0; j < lgrp_spaces()->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
218 if (lgrp_spaces()->at(j)->lgrp_id() == lgrp_ids[i]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 found = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
220 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
221 }
a61af66fc99e Initial load
duke
parents:
diff changeset
222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
223 if (!found) {
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
224 lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i], alignment()));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // Remove spaces for the removed nodes.
a61af66fc99e Initial load
duke
parents:
diff changeset
229 for (int i = 0; i < lgrp_spaces()->length();) {
a61af66fc99e Initial load
duke
parents:
diff changeset
230 bool found = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 for (int j = 0; j < lgrp_num; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
232 if (lgrp_spaces()->at(i)->lgrp_id() == lgrp_ids[j]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 found = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
234 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
237 if (!found) {
a61af66fc99e Initial load
duke
parents:
diff changeset
238 delete lgrp_spaces()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
239 lgrp_spaces()->remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
240 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
241 i++;
a61af66fc99e Initial load
duke
parents:
diff changeset
242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
244
a61af66fc99e Initial load
duke
parents:
diff changeset
245 FREE_C_HEAP_ARRAY(int, lgrp_ids);
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 if (changed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
249 thread->set_lgrp_id(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
252 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
254 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
255 }
a61af66fc99e Initial load
duke
parents:
diff changeset
256
a61af66fc99e Initial load
duke
parents:
diff changeset
257 // Bias region towards the first-touching lgrp. Set the right page sizes.
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
258 void MutableNUMASpace::bias_region(MemRegion mr, int lgrp_id) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
259 HeapWord *start = (HeapWord*)round_to((intptr_t)mr.start(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
260 HeapWord *end = (HeapWord*)round_down((intptr_t)mr.end(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
261 if (end > start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
262 MemRegion aligned_region(start, end);
a61af66fc99e Initial load
duke
parents:
diff changeset
263 assert((intptr_t)aligned_region.start() % page_size() == 0 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
264 (intptr_t)aligned_region.byte_size() % page_size() == 0, "Bad alignment");
a61af66fc99e Initial load
duke
parents:
diff changeset
265 assert(region().contains(aligned_region), "Sanity");
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
266 // First we tell the OS which page size we want in the given range. The underlying
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
267 // large page can be broken down if we require small pages.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
268 os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), page_size());
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
269 // Then we uncommit the pages in the range.
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
270 os::free_memory((char*)aligned_region.start(), aligned_region.byte_size());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
271 // And make them local/first-touch biased.
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
272 os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), lgrp_id);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
275
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // Free all pages in the region.
a61af66fc99e Initial load
duke
parents:
diff changeset
277 void MutableNUMASpace::free_region(MemRegion mr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
278 HeapWord *start = (HeapWord*)round_to((intptr_t)mr.start(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
279 HeapWord *end = (HeapWord*)round_down((intptr_t)mr.end(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
280 if (end > start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
281 MemRegion aligned_region(start, end);
a61af66fc99e Initial load
duke
parents:
diff changeset
282 assert((intptr_t)aligned_region.start() % page_size() == 0 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
283 (intptr_t)aligned_region.byte_size() % page_size() == 0, "Bad alignment");
a61af66fc99e Initial load
duke
parents:
diff changeset
284 assert(region().contains(aligned_region), "Sanity");
a61af66fc99e Initial load
duke
parents:
diff changeset
285 os::free_memory((char*)aligned_region.start(), aligned_region.byte_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
286 }
a61af66fc99e Initial load
duke
parents:
diff changeset
287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
288
a61af66fc99e Initial load
duke
parents:
diff changeset
289 // Update space layout. Perform adaptation.
a61af66fc99e Initial load
duke
parents:
diff changeset
290 void MutableNUMASpace::update() {
a61af66fc99e Initial load
duke
parents:
diff changeset
291 if (update_layout(false)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // If the topology has changed, make all chunks zero-sized.
268
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
293 // And clear the alloc-rate statistics.
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
294 // In future we may want to handle this more gracefully in order
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
295 // to avoid the reallocation of the pages as much as possible.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
296 for (int i = 0; i < lgrp_spaces()->length(); i++) {
268
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
297 LGRPSpace *ls = lgrp_spaces()->at(i);
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
298 MutableSpace *s = ls->space();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
299 s->set_end(s->bottom());
a61af66fc99e Initial load
duke
parents:
diff changeset
300 s->set_top(s->bottom());
268
d6340ab4105b 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set")
iveresov
parents: 263
diff changeset
301 ls->clear_alloc_rate();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
302 }
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
303 // A NUMA space is never mangled
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
304 initialize(region(),
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
305 SpaceDecorator::Clear,
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
306 SpaceDecorator::DontMangle);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
307 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
308 bool should_initialize = false;
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
309 if (!os::numa_has_static_binding()) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
310 for (int i = 0; i < lgrp_spaces()->length(); i++) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
311 if (!lgrp_spaces()->at(i)->invalid_region().is_empty()) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
312 should_initialize = true;
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
313 break;
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
314 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
317
a61af66fc99e Initial load
duke
parents:
diff changeset
318 if (should_initialize ||
a61af66fc99e Initial load
duke
parents:
diff changeset
319 (UseAdaptiveNUMAChunkSizing && adaptation_cycles() < samples_count())) {
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
320 // A NUMA space is never mangled
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
321 initialize(region(),
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
322 SpaceDecorator::Clear,
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
323 SpaceDecorator::DontMangle);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
324 }
a61af66fc99e Initial load
duke
parents:
diff changeset
325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
326
a61af66fc99e Initial load
duke
parents:
diff changeset
327 if (NUMAStats) {
a61af66fc99e Initial load
duke
parents:
diff changeset
328 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
329 lgrp_spaces()->at(i)->accumulate_statistics(page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
331 }
a61af66fc99e Initial load
duke
parents:
diff changeset
332
a61af66fc99e Initial load
duke
parents:
diff changeset
333 scan_pages(NUMAPageScanRate);
a61af66fc99e Initial load
duke
parents:
diff changeset
334 }
a61af66fc99e Initial load
duke
parents:
diff changeset
335
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // Scan pages. Free pages that have smaller size or wrong placement.
a61af66fc99e Initial load
duke
parents:
diff changeset
337 void MutableNUMASpace::scan_pages(size_t page_count)
a61af66fc99e Initial load
duke
parents:
diff changeset
338 {
a61af66fc99e Initial load
duke
parents:
diff changeset
339 size_t pages_per_chunk = page_count / lgrp_spaces()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
340 if (pages_per_chunk > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
342 LGRPSpace *ls = lgrp_spaces()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
343 ls->scan_pages(page_size(), pages_per_chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
344 }
a61af66fc99e Initial load
duke
parents:
diff changeset
345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
347
a61af66fc99e Initial load
duke
parents:
diff changeset
348 // Accumulate statistics about the allocation rate of each lgrp.
a61af66fc99e Initial load
duke
parents:
diff changeset
349 void MutableNUMASpace::accumulate_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 if (UseAdaptiveNUMAChunkSizing) {
a61af66fc99e Initial load
duke
parents:
diff changeset
351 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
352 lgrp_spaces()->at(i)->sample();
a61af66fc99e Initial load
duke
parents:
diff changeset
353 }
a61af66fc99e Initial load
duke
parents:
diff changeset
354 increment_samples_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
355 }
a61af66fc99e Initial load
duke
parents:
diff changeset
356
a61af66fc99e Initial load
duke
parents:
diff changeset
357 if (NUMAStats) {
a61af66fc99e Initial load
duke
parents:
diff changeset
358 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
359 lgrp_spaces()->at(i)->accumulate_statistics(page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
362 }
a61af66fc99e Initial load
duke
parents:
diff changeset
363
a61af66fc99e Initial load
duke
parents:
diff changeset
364 // Get the current size of a chunk.
a61af66fc99e Initial load
duke
parents:
diff changeset
365 // This function computes the size of the chunk based on the
a61af66fc99e Initial load
duke
parents:
diff changeset
366 // difference between chunk ends. This allows it to work correctly in
a61af66fc99e Initial load
duke
parents:
diff changeset
367 // case the whole space is resized and during the process of adaptive
a61af66fc99e Initial load
duke
parents:
diff changeset
368 // chunk resizing.
a61af66fc99e Initial load
duke
parents:
diff changeset
369 size_t MutableNUMASpace::current_chunk_size(int i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
370 HeapWord *cur_end, *prev_end;
a61af66fc99e Initial load
duke
parents:
diff changeset
371 if (i == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
372 prev_end = bottom();
a61af66fc99e Initial load
duke
parents:
diff changeset
373 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
374 prev_end = lgrp_spaces()->at(i - 1)->space()->end();
a61af66fc99e Initial load
duke
parents:
diff changeset
375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
376 if (i == lgrp_spaces()->length() - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
377 cur_end = end();
a61af66fc99e Initial load
duke
parents:
diff changeset
378 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
379 cur_end = lgrp_spaces()->at(i)->space()->end();
a61af66fc99e Initial load
duke
parents:
diff changeset
380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
381 if (cur_end > prev_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
382 return pointer_delta(cur_end, prev_end, sizeof(char));
a61af66fc99e Initial load
duke
parents:
diff changeset
383 }
a61af66fc99e Initial load
duke
parents:
diff changeset
384 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
385 }
a61af66fc99e Initial load
duke
parents:
diff changeset
386
a61af66fc99e Initial load
duke
parents:
diff changeset
387 // Return the default chunk size by equally diving the space.
a61af66fc99e Initial load
duke
parents:
diff changeset
388 // page_size() aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
389 size_t MutableNUMASpace::default_chunk_size() {
a61af66fc99e Initial load
duke
parents:
diff changeset
390 return base_space_size() / lgrp_spaces()->length() * page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392
a61af66fc99e Initial load
duke
parents:
diff changeset
393 // Produce a new chunk size. page_size() aligned.
391
ab4a7734b9c4 6753547: NUMA allocator: Invalid chunk size computation during adaptive resizing
iveresov
parents: 373
diff changeset
394 // This function is expected to be called on sequence of i's from 0 to
ab4a7734b9c4 6753547: NUMA allocator: Invalid chunk size computation during adaptive resizing
iveresov
parents: 373
diff changeset
395 // lgrp_spaces()->length().
0
a61af66fc99e Initial load
duke
parents:
diff changeset
396 size_t MutableNUMASpace::adaptive_chunk_size(int i, size_t limit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
397 size_t pages_available = base_space_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
398 for (int j = 0; j < i; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
399 pages_available -= round_down(current_chunk_size(j), page_size()) / page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
401 pages_available -= lgrp_spaces()->length() - i - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
402 assert(pages_available > 0, "No pages left");
a61af66fc99e Initial load
duke
parents:
diff changeset
403 float alloc_rate = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
404 for (int j = i; j < lgrp_spaces()->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
405 alloc_rate += lgrp_spaces()->at(j)->alloc_rate()->average();
a61af66fc99e Initial load
duke
parents:
diff changeset
406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
407 size_t chunk_size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
408 if (alloc_rate > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
409 LGRPSpace *ls = lgrp_spaces()->at(i);
391
ab4a7734b9c4 6753547: NUMA allocator: Invalid chunk size computation during adaptive resizing
iveresov
parents: 373
diff changeset
410 chunk_size = (size_t)(ls->alloc_rate()->average() / alloc_rate * pages_available) * page_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
411 }
a61af66fc99e Initial load
duke
parents:
diff changeset
412 chunk_size = MAX2(chunk_size, page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
413
a61af66fc99e Initial load
duke
parents:
diff changeset
414 if (limit > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
415 limit = round_down(limit, page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
416 if (chunk_size > current_chunk_size(i)) {
462
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
417 size_t upper_bound = pages_available * page_size();
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
418 if (upper_bound > limit &&
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
419 current_chunk_size(i) < upper_bound - limit) {
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
420 // The resulting upper bound should not exceed the available
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
421 // amount of memory (pages_available * page_size()).
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
422 upper_bound = current_chunk_size(i) + limit;
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
423 }
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
424 chunk_size = MIN2(chunk_size, upper_bound);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
425 } else {
462
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
426 size_t lower_bound = page_size();
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
427 if (current_chunk_size(i) > limit) { // lower_bound shouldn't underflow.
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
428 lower_bound = current_chunk_size(i) - limit;
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
429 }
85f1b9537f70 6779436: NUMA allocator: libnuma expects certain size of the buffer in numa_node_to_cpus()
iveresov
parents: 391
diff changeset
430 chunk_size = MAX2(chunk_size, lower_bound);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
431 }
a61af66fc99e Initial load
duke
parents:
diff changeset
432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
433 assert(chunk_size <= pages_available * page_size(), "Chunk size out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
434 return chunk_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
436
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // Return the bottom_region and the top_region. Align them to page_size() boundary.
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // |------------------new_region---------------------------------|
a61af66fc99e Initial load
duke
parents:
diff changeset
440 // |----bottom_region--|---intersection---|------top_region------|
a61af66fc99e Initial load
duke
parents:
diff changeset
441 void MutableNUMASpace::select_tails(MemRegion new_region, MemRegion intersection,
a61af66fc99e Initial load
duke
parents:
diff changeset
442 MemRegion* bottom_region, MemRegion *top_region) {
a61af66fc99e Initial load
duke
parents:
diff changeset
443 // Is there bottom?
a61af66fc99e Initial load
duke
parents:
diff changeset
444 if (new_region.start() < intersection.start()) { // Yes
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // Try to coalesce small pages into a large one.
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
446 if (UseLargePages && page_size() >= alignment()) {
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
447 HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), alignment());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
448 if (new_region.contains(p)
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
449 && pointer_delta(p, new_region.start(), sizeof(char)) >= alignment()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
450 if (intersection.contains(p)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
451 intersection = MemRegion(p, intersection.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
452 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
453 intersection = MemRegion(p, p);
a61af66fc99e Initial load
duke
parents:
diff changeset
454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
455 }
a61af66fc99e Initial load
duke
parents:
diff changeset
456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
457 *bottom_region = MemRegion(new_region.start(), intersection.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
458 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 *bottom_region = MemRegion();
a61af66fc99e Initial load
duke
parents:
diff changeset
460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
461
a61af66fc99e Initial load
duke
parents:
diff changeset
462 // Is there top?
a61af66fc99e Initial load
duke
parents:
diff changeset
463 if (intersection.end() < new_region.end()) { // Yes
a61af66fc99e Initial load
duke
parents:
diff changeset
464 // Try to coalesce small pages into a large one.
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
465 if (UseLargePages && page_size() >= alignment()) {
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
466 HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), alignment());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
467 if (new_region.contains(p)
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
468 && pointer_delta(new_region.end(), p, sizeof(char)) >= alignment()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
469 if (intersection.contains(p)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
470 intersection = MemRegion(intersection.start(), p);
a61af66fc99e Initial load
duke
parents:
diff changeset
471 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
472 intersection = MemRegion(p, p);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
475 }
a61af66fc99e Initial load
duke
parents:
diff changeset
476 *top_region = MemRegion(intersection.end(), new_region.end());
a61af66fc99e Initial load
duke
parents:
diff changeset
477 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
478 *top_region = MemRegion();
a61af66fc99e Initial load
duke
parents:
diff changeset
479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481
a61af66fc99e Initial load
duke
parents:
diff changeset
482 // Try to merge the invalid region with the bottom or top region by decreasing
a61af66fc99e Initial load
duke
parents:
diff changeset
483 // the intersection area. Return the invalid_region aligned to the page_size()
a61af66fc99e Initial load
duke
parents:
diff changeset
484 // boundary if it's inside the intersection. Return non-empty invalid_region
a61af66fc99e Initial load
duke
parents:
diff changeset
485 // if it lies inside the intersection (also page-aligned).
a61af66fc99e Initial load
duke
parents:
diff changeset
486 // |------------------new_region---------------------------------|
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // |----------------|-------invalid---|--------------------------|
a61af66fc99e Initial load
duke
parents:
diff changeset
488 // |----bottom_region--|---intersection---|------top_region------|
a61af66fc99e Initial load
duke
parents:
diff changeset
489 void MutableNUMASpace::merge_regions(MemRegion new_region, MemRegion* intersection,
a61af66fc99e Initial load
duke
parents:
diff changeset
490 MemRegion *invalid_region) {
a61af66fc99e Initial load
duke
parents:
diff changeset
491 if (intersection->start() >= invalid_region->start() && intersection->contains(invalid_region->end())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
492 *intersection = MemRegion(invalid_region->end(), intersection->end());
a61af66fc99e Initial load
duke
parents:
diff changeset
493 *invalid_region = MemRegion();
a61af66fc99e Initial load
duke
parents:
diff changeset
494 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
495 if (intersection->end() <= invalid_region->end() && intersection->contains(invalid_region->start())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
496 *intersection = MemRegion(intersection->start(), invalid_region->start());
a61af66fc99e Initial load
duke
parents:
diff changeset
497 *invalid_region = MemRegion();
a61af66fc99e Initial load
duke
parents:
diff changeset
498 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
499 if (intersection->equals(*invalid_region) || invalid_region->contains(*intersection)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
500 *intersection = MemRegion(new_region.start(), new_region.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
501 *invalid_region = MemRegion();
a61af66fc99e Initial load
duke
parents:
diff changeset
502 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
503 if (intersection->contains(invalid_region)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
504 // That's the only case we have to make an additional bias_region() call.
a61af66fc99e Initial load
duke
parents:
diff changeset
505 HeapWord* start = invalid_region->start();
a61af66fc99e Initial load
duke
parents:
diff changeset
506 HeapWord* end = invalid_region->end();
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
507 if (UseLargePages && page_size() >= alignment()) {
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
508 HeapWord *p = (HeapWord*)round_down((intptr_t) start, alignment());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
509 if (new_region.contains(p)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
510 start = p;
a61af66fc99e Initial load
duke
parents:
diff changeset
511 }
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
512 p = (HeapWord*)round_to((intptr_t) end, alignment());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
513 if (new_region.contains(end)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
514 end = p;
a61af66fc99e Initial load
duke
parents:
diff changeset
515 }
a61af66fc99e Initial load
duke
parents:
diff changeset
516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
517 if (intersection->start() > start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
518 *intersection = MemRegion(start, intersection->end());
a61af66fc99e Initial load
duke
parents:
diff changeset
519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
520 if (intersection->end() < end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
521 *intersection = MemRegion(intersection->start(), end);
a61af66fc99e Initial load
duke
parents:
diff changeset
522 }
a61af66fc99e Initial load
duke
parents:
diff changeset
523 *invalid_region = MemRegion(start, end);
a61af66fc99e Initial load
duke
parents:
diff changeset
524 }
a61af66fc99e Initial load
duke
parents:
diff changeset
525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
526
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
527 void MutableNUMASpace::initialize(MemRegion mr,
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
528 bool clear_space,
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
529 bool mangle_space,
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
530 bool setup_pages) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
531 assert(clear_space, "Reallocation will destory data!");
a61af66fc99e Initial load
duke
parents:
diff changeset
532 assert(lgrp_spaces()->length() > 0, "There should be at least one space");
a61af66fc99e Initial load
duke
parents:
diff changeset
533
a61af66fc99e Initial load
duke
parents:
diff changeset
534 MemRegion old_region = region(), new_region;
a61af66fc99e Initial load
duke
parents:
diff changeset
535 set_bottom(mr.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
536 set_end(mr.end());
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
537 // Must always clear the space
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
538 clear(SpaceDecorator::DontMangle);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
539
a61af66fc99e Initial load
duke
parents:
diff changeset
540 // Compute chunk sizes
a61af66fc99e Initial load
duke
parents:
diff changeset
541 size_t prev_page_size = page_size();
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
542 set_page_size(UseLargePages ? alignment() : os::vm_page_size());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
543 HeapWord* rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
544 HeapWord* rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
545 size_t base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
546
a61af66fc99e Initial load
duke
parents:
diff changeset
547 // Try small pages if the chunk size is too small
a61af66fc99e Initial load
duke
parents:
diff changeset
548 if (base_space_size_pages / lgrp_spaces()->length() == 0
a61af66fc99e Initial load
duke
parents:
diff changeset
549 && page_size() > (size_t)os::vm_page_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
550 set_page_size(os::vm_page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
551 rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
552 rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
553 base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
554 }
a61af66fc99e Initial load
duke
parents:
diff changeset
555 guarantee(base_space_size_pages / lgrp_spaces()->length() > 0, "Space too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
556 set_base_space_size(base_space_size_pages);
a61af66fc99e Initial load
duke
parents:
diff changeset
557
a61af66fc99e Initial load
duke
parents:
diff changeset
558 // Handle space resize
a61af66fc99e Initial load
duke
parents:
diff changeset
559 MemRegion top_region, bottom_region;
a61af66fc99e Initial load
duke
parents:
diff changeset
560 if (!old_region.equals(region())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
561 new_region = MemRegion(rounded_bottom, rounded_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
562 MemRegion intersection = new_region.intersection(old_region);
a61af66fc99e Initial load
duke
parents:
diff changeset
563 if (intersection.start() == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
564 intersection.end() == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
565 prev_page_size > page_size()) { // If the page size got smaller we have to change
a61af66fc99e Initial load
duke
parents:
diff changeset
566 // the page size preference for the whole space.
a61af66fc99e Initial load
duke
parents:
diff changeset
567 intersection = MemRegion(new_region.start(), new_region.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
568 }
a61af66fc99e Initial load
duke
parents:
diff changeset
569 select_tails(new_region, intersection, &bottom_region, &top_region);
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
570 bias_region(bottom_region, lgrp_spaces()->at(0)->lgrp_id());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
571 bias_region(top_region, lgrp_spaces()->at(lgrp_spaces()->length() - 1)->lgrp_id());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
573
a61af66fc99e Initial load
duke
parents:
diff changeset
574 // Check if the space layout has changed significantly?
a61af66fc99e Initial load
duke
parents:
diff changeset
575 // This happens when the space has been resized so that either head or tail
a61af66fc99e Initial load
duke
parents:
diff changeset
576 // chunk became less than a page.
a61af66fc99e Initial load
duke
parents:
diff changeset
577 bool layout_valid = UseAdaptiveNUMAChunkSizing &&
a61af66fc99e Initial load
duke
parents:
diff changeset
578 current_chunk_size(0) > page_size() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
579 current_chunk_size(lgrp_spaces()->length() - 1) > page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
580
a61af66fc99e Initial load
duke
parents:
diff changeset
581
a61af66fc99e Initial load
duke
parents:
diff changeset
582 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
583 LGRPSpace *ls = lgrp_spaces()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
584 MutableSpace *s = ls->space();
a61af66fc99e Initial load
duke
parents:
diff changeset
585 old_region = s->region();
a61af66fc99e Initial load
duke
parents:
diff changeset
586
a61af66fc99e Initial load
duke
parents:
diff changeset
587 size_t chunk_byte_size = 0, old_chunk_byte_size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
588 if (i < lgrp_spaces()->length() - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
589 if (!UseAdaptiveNUMAChunkSizing ||
a61af66fc99e Initial load
duke
parents:
diff changeset
590 (UseAdaptiveNUMAChunkSizing && NUMAChunkResizeWeight == 0) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
591 samples_count() < AdaptiveSizePolicyReadyThreshold) {
a61af66fc99e Initial load
duke
parents:
diff changeset
592 // No adaptation. Divide the space equally.
a61af66fc99e Initial load
duke
parents:
diff changeset
593 chunk_byte_size = default_chunk_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
594 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
595 if (!layout_valid || NUMASpaceResizeRate == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
596 // Fast adaptation. If no space resize rate is set, resize
a61af66fc99e Initial load
duke
parents:
diff changeset
597 // the chunks instantly.
a61af66fc99e Initial load
duke
parents:
diff changeset
598 chunk_byte_size = adaptive_chunk_size(i, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
599 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
600 // Slow adaptation. Resize the chunks moving no more than
a61af66fc99e Initial load
duke
parents:
diff changeset
601 // NUMASpaceResizeRate bytes per collection.
a61af66fc99e Initial load
duke
parents:
diff changeset
602 size_t limit = NUMASpaceResizeRate /
a61af66fc99e Initial load
duke
parents:
diff changeset
603 (lgrp_spaces()->length() * (lgrp_spaces()->length() + 1) / 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
604 chunk_byte_size = adaptive_chunk_size(i, MAX2(limit * (i + 1), page_size()));
a61af66fc99e Initial load
duke
parents:
diff changeset
605 }
a61af66fc99e Initial load
duke
parents:
diff changeset
606
a61af66fc99e Initial load
duke
parents:
diff changeset
607 assert(chunk_byte_size >= page_size(), "Chunk size too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
608 assert(chunk_byte_size <= capacity_in_bytes(), "Sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
609 }
a61af66fc99e Initial load
duke
parents:
diff changeset
610
a61af66fc99e Initial load
duke
parents:
diff changeset
611 if (i == 0) { // Bottom chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
612 if (i != lgrp_spaces()->length() - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
613 new_region = MemRegion(bottom(), rounded_bottom + (chunk_byte_size >> LogHeapWordSize));
a61af66fc99e Initial load
duke
parents:
diff changeset
614 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
615 new_region = MemRegion(bottom(), end());
a61af66fc99e Initial load
duke
parents:
diff changeset
616 }
a61af66fc99e Initial load
duke
parents:
diff changeset
617 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
618 if (i < lgrp_spaces()->length() - 1) { // Middle chunks
a61af66fc99e Initial load
duke
parents:
diff changeset
619 MutableSpace *ps = lgrp_spaces()->at(i - 1)->space();
a61af66fc99e Initial load
duke
parents:
diff changeset
620 new_region = MemRegion(ps->end(),
a61af66fc99e Initial load
duke
parents:
diff changeset
621 ps->end() + (chunk_byte_size >> LogHeapWordSize));
a61af66fc99e Initial load
duke
parents:
diff changeset
622 } else { // Top chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
623 MutableSpace *ps = lgrp_spaces()->at(i - 1)->space();
a61af66fc99e Initial load
duke
parents:
diff changeset
624 new_region = MemRegion(ps->end(), end());
a61af66fc99e Initial load
duke
parents:
diff changeset
625 }
a61af66fc99e Initial load
duke
parents:
diff changeset
626 guarantee(region().contains(new_region), "Region invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
627
a61af66fc99e Initial load
duke
parents:
diff changeset
628
a61af66fc99e Initial load
duke
parents:
diff changeset
629 // The general case:
a61af66fc99e Initial load
duke
parents:
diff changeset
630 // |---------------------|--invalid---|--------------------------|
a61af66fc99e Initial load
duke
parents:
diff changeset
631 // |------------------new_region---------------------------------|
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // |----bottom_region--|---intersection---|------top_region------|
a61af66fc99e Initial load
duke
parents:
diff changeset
633 // |----old_region----|
a61af66fc99e Initial load
duke
parents:
diff changeset
634 // The intersection part has all pages in place we don't need to migrate them.
a61af66fc99e Initial load
duke
parents:
diff changeset
635 // Pages for the top and bottom part should be freed and then reallocated.
a61af66fc99e Initial load
duke
parents:
diff changeset
636
a61af66fc99e Initial load
duke
parents:
diff changeset
637 MemRegion intersection = old_region.intersection(new_region);
a61af66fc99e Initial load
duke
parents:
diff changeset
638
a61af66fc99e Initial load
duke
parents:
diff changeset
639 if (intersection.start() == NULL || intersection.end() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
640 intersection = MemRegion(new_region.start(), new_region.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
642
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
643 if (!os::numa_has_static_binding()) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
644 MemRegion invalid_region = ls->invalid_region().intersection(new_region);
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
645 // Invalid region is a range of memory that could've possibly
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
646 // been allocated on the other node. That's relevant only on Solaris where
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
647 // there is no static memory binding.
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
648 if (!invalid_region.is_empty()) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
649 merge_regions(new_region, &intersection, &invalid_region);
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
650 free_region(invalid_region);
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
651 ls->set_invalid_region(MemRegion());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
652 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
653 }
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
654
0
a61af66fc99e Initial load
duke
parents:
diff changeset
655 select_tails(new_region, intersection, &bottom_region, &top_region);
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
656
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
657 if (!os::numa_has_static_binding()) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
658 // If that's a system with the first-touch policy then it's enough
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
659 // to free the pages.
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
660 free_region(bottom_region);
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
661 free_region(top_region);
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
662 } else {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
663 // In a system with static binding we have to change the bias whenever
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
664 // we reshape the heap.
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
665 bias_region(bottom_region, ls->lgrp_id());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
666 bias_region(top_region, ls->lgrp_id());
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
667 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
668
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
669 // Clear space (set top = bottom) but never mangle.
535
4e400c36026f 6783381: NUMA allocator: don't pretouch eden space with UseNUMA
iveresov
parents: 481
diff changeset
670 s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle, MutableSpace::DontSetupPages);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
671
a61af66fc99e Initial load
duke
parents:
diff changeset
672 set_adaptation_cycles(samples_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
674 }
a61af66fc99e Initial load
duke
parents:
diff changeset
675
a61af66fc99e Initial load
duke
parents:
diff changeset
676 // Set the top of the whole space.
a61af66fc99e Initial load
duke
parents:
diff changeset
677 // Mark the the holes in chunks below the top() as invalid.
a61af66fc99e Initial load
duke
parents:
diff changeset
678 void MutableNUMASpace::set_top(HeapWord* value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
679 bool found_top = false;
190
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
680 for (int i = 0; i < lgrp_spaces()->length();) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
681 LGRPSpace *ls = lgrp_spaces()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
682 MutableSpace *s = ls->space();
a61af66fc99e Initial load
duke
parents:
diff changeset
683 HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
a61af66fc99e Initial load
duke
parents:
diff changeset
684
a61af66fc99e Initial load
duke
parents:
diff changeset
685 if (s->contains(value)) {
190
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
686 // Check if setting the chunk's top to a given value would create a hole less than
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
687 // a minimal object; assuming that's not the last chunk in which case we don't care.
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
688 if (i < lgrp_spaces()->length() - 1) {
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
689 size_t remainder = pointer_delta(s->end(), value);
481
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 462
diff changeset
690 const size_t min_fill_size = CollectedHeap::min_fill_size();
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 462
diff changeset
691 if (remainder < min_fill_size && remainder > 0) {
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 462
diff changeset
692 // Add a minimum size filler object; it will cross the chunk boundary.
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 462
diff changeset
693 CollectedHeap::fill_with_object(value, min_fill_size);
7d7a7c599c17 6578152: fill_region_with_object has usability and safety issues
jcoomes
parents: 462
diff changeset
694 value += min_fill_size;
190
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
695 assert(!s->contains(value), "Should be in the next chunk");
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
696 // Restart the loop from the same chunk, since the value has moved
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
697 // to the next one.
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
698 continue;
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
699 }
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
700 }
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
701
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
702 if (!os::numa_has_static_binding() && top < value && top < s->end()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
703 ls->add_invalid_region(MemRegion(top, value));
a61af66fc99e Initial load
duke
parents:
diff changeset
704 }
a61af66fc99e Initial load
duke
parents:
diff changeset
705 s->set_top(value);
a61af66fc99e Initial load
duke
parents:
diff changeset
706 found_top = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
707 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
708 if (found_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
709 s->set_top(s->bottom());
a61af66fc99e Initial load
duke
parents:
diff changeset
710 } else {
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
711 if (!os::numa_has_static_binding() && top < s->end()) {
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
712 ls->add_invalid_region(MemRegion(top, s->end()));
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
713 }
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
714 s->set_top(s->end());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
716 }
190
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
717 i++;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
719 MutableSpace::set_top(value);
a61af66fc99e Initial load
duke
parents:
diff changeset
720 }
a61af66fc99e Initial load
duke
parents:
diff changeset
721
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
722 void MutableNUMASpace::clear(bool mangle_space) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
723 MutableSpace::set_top(bottom());
a61af66fc99e Initial load
duke
parents:
diff changeset
724 for (int i = 0; i < lgrp_spaces()->length(); i++) {
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
725 // Never mangle NUMA spaces because the mangling will
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
726 // bind the memory to a possibly unwanted lgroup.
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 190
diff changeset
727 lgrp_spaces()->at(i)->space()->clear(SpaceDecorator::DontMangle);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
728 }
a61af66fc99e Initial load
duke
parents:
diff changeset
729 }
a61af66fc99e Initial load
duke
parents:
diff changeset
730
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
731 /*
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
732 Linux supports static memory binding, therefore the most part of the
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
733 logic dealing with the possible invalid page allocation is effectively
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
734 disabled. Besides there is no notion of the home node in Linux. A
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
735 thread is allowed to migrate freely. Although the scheduler is rather
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
736 reluctant to move threads between the nodes. We check for the current
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
737 node every allocation. And with a high probability a thread stays on
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
738 the same node for some time allowing local access to recently allocated
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
739 objects.
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
740 */
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
741
0
a61af66fc99e Initial load
duke
parents:
diff changeset
742 HeapWord* MutableNUMASpace::allocate(size_t size) {
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
743 Thread* thr = Thread::current();
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
744 int lgrp_id = thr->lgrp_id();
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
745 if (lgrp_id == -1 || !os::numa_has_group_homing()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
746 lgrp_id = os::numa_get_group_id();
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
747 thr->set_lgrp_id(lgrp_id);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
749
a61af66fc99e Initial load
duke
parents:
diff changeset
750 int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
a61af66fc99e Initial load
duke
parents:
diff changeset
751
a61af66fc99e Initial load
duke
parents:
diff changeset
752 // It is possible that a new CPU has been hotplugged and
a61af66fc99e Initial load
duke
parents:
diff changeset
753 // we haven't reshaped the space accordingly.
a61af66fc99e Initial load
duke
parents:
diff changeset
754 if (i == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
755 i = os::random() % lgrp_spaces()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
756 }
a61af66fc99e Initial load
duke
parents:
diff changeset
757
373
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
758 LGRPSpace* ls = lgrp_spaces()->at(i);
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
759 MutableSpace *s = ls->space();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
760 HeapWord *p = s->allocate(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
761
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
762 if (p != NULL) {
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
763 size_t remainder = s->free_in_words();
1571
2d127394260e 6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents: 628
diff changeset
764 if (remainder < CollectedHeap::min_fill_size() && remainder > 0) {
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
765 s->set_top(s->top() - size);
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
766 p = NULL;
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
767 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
768 }
a61af66fc99e Initial load
duke
parents:
diff changeset
769 if (p != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
770 if (top() < s->top()) { // Keep _top updated.
a61af66fc99e Initial load
duke
parents:
diff changeset
771 MutableSpace::set_top(s->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
772 }
a61af66fc99e Initial load
duke
parents:
diff changeset
773 }
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
774 // Make the page allocation happen here if there is no static binding..
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
775 if (p != NULL && !os::numa_has_static_binding()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
776 for (HeapWord *i = p; i < p + size; i += os::vm_page_size() >> LogHeapWordSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
777 *(int*)i = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
778 }
a61af66fc99e Initial load
duke
parents:
diff changeset
779 }
373
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
780 if (p == NULL) {
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
781 ls->set_allocation_failed();
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
782 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
783 return p;
a61af66fc99e Initial load
duke
parents:
diff changeset
784 }
a61af66fc99e Initial load
duke
parents:
diff changeset
785
a61af66fc99e Initial load
duke
parents:
diff changeset
786 // This version is lock-free.
a61af66fc99e Initial load
duke
parents:
diff changeset
787 HeapWord* MutableNUMASpace::cas_allocate(size_t size) {
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
788 Thread* thr = Thread::current();
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
789 int lgrp_id = thr->lgrp_id();
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
790 if (lgrp_id == -1 || !os::numa_has_group_homing()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
791 lgrp_id = os::numa_get_group_id();
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
792 thr->set_lgrp_id(lgrp_id);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
793 }
a61af66fc99e Initial load
duke
parents:
diff changeset
794
a61af66fc99e Initial load
duke
parents:
diff changeset
795 int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals);
a61af66fc99e Initial load
duke
parents:
diff changeset
796 // It is possible that a new CPU has been hotplugged and
a61af66fc99e Initial load
duke
parents:
diff changeset
797 // we haven't reshaped the space accordingly.
a61af66fc99e Initial load
duke
parents:
diff changeset
798 if (i == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
799 i = os::random() % lgrp_spaces()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
800 }
373
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
801 LGRPSpace *ls = lgrp_spaces()->at(i);
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
802 MutableSpace *s = ls->space();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
803 HeapWord *p = s->cas_allocate(size);
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
804 if (p != NULL) {
190
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
805 size_t remainder = pointer_delta(s->end(), p + size);
1571
2d127394260e 6916623: Align object to 16 bytes to use Compressed Oops with java heap up to 64Gb
kvn
parents: 628
diff changeset
806 if (remainder < CollectedHeap::min_fill_size() && remainder > 0) {
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
807 if (s->cas_deallocate(p, size)) {
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
808 // We were the last to allocate and created a fragment less than
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
809 // a minimal object.
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
810 p = NULL;
190
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
811 } else {
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
812 guarantee(false, "Deallocation should always succeed");
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
813 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
816 if (p != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
817 HeapWord* cur_top, *cur_chunk_top = p + size;
a61af66fc99e Initial load
duke
parents:
diff changeset
818 while ((cur_top = top()) < cur_chunk_top) { // Keep _top updated.
a61af66fc99e Initial load
duke
parents:
diff changeset
819 if (Atomic::cmpxchg_ptr(cur_chunk_top, top_addr(), cur_top) == cur_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
820 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
821 }
a61af66fc99e Initial load
duke
parents:
diff changeset
822 }
a61af66fc99e Initial load
duke
parents:
diff changeset
823 }
a61af66fc99e Initial load
duke
parents:
diff changeset
824
141
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
825 // Make the page allocation happen here if there is no static binding.
fcbfc50865ab 6684395: Port NUMA-aware allocator to linux
iveresov
parents: 0
diff changeset
826 if (p != NULL && !os::numa_has_static_binding() ) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
827 for (HeapWord *i = p; i < p + size; i += os::vm_page_size() >> LogHeapWordSize) {
a61af66fc99e Initial load
duke
parents:
diff changeset
828 *(int*)i = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
829 }
a61af66fc99e Initial load
duke
parents:
diff changeset
830 }
373
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
831 if (p == NULL) {
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
832 ls->set_allocation_failed();
06df86c2ec37 6740923: NUMA allocator: Ensure the progress of adaptive chunk resizing
iveresov
parents: 269
diff changeset
833 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
834 return p;
a61af66fc99e Initial load
duke
parents:
diff changeset
835 }
a61af66fc99e Initial load
duke
parents:
diff changeset
836
a61af66fc99e Initial load
duke
parents:
diff changeset
837 void MutableNUMASpace::print_short_on(outputStream* st) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
838 MutableSpace::print_short_on(st);
a61af66fc99e Initial load
duke
parents:
diff changeset
839 st->print(" (");
a61af66fc99e Initial load
duke
parents:
diff changeset
840 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
841 st->print("lgrp %d: ", lgrp_spaces()->at(i)->lgrp_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
842 lgrp_spaces()->at(i)->space()->print_short_on(st);
a61af66fc99e Initial load
duke
parents:
diff changeset
843 if (i < lgrp_spaces()->length() - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
844 st->print(", ");
a61af66fc99e Initial load
duke
parents:
diff changeset
845 }
a61af66fc99e Initial load
duke
parents:
diff changeset
846 }
a61af66fc99e Initial load
duke
parents:
diff changeset
847 st->print(")");
a61af66fc99e Initial load
duke
parents:
diff changeset
848 }
a61af66fc99e Initial load
duke
parents:
diff changeset
849
a61af66fc99e Initial load
duke
parents:
diff changeset
850 void MutableNUMASpace::print_on(outputStream* st) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
851 MutableSpace::print_on(st);
a61af66fc99e Initial load
duke
parents:
diff changeset
852 for (int i = 0; i < lgrp_spaces()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
853 LGRPSpace *ls = lgrp_spaces()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
854 st->print(" lgrp %d", ls->lgrp_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
855 ls->space()->print_on(st);
a61af66fc99e Initial load
duke
parents:
diff changeset
856 if (NUMAStats) {
144
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
857 for (int i = 0; i < lgrp_spaces()->length(); i++) {
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
858 lgrp_spaces()->at(i)->accumulate_statistics(page_size());
e3729351c946 6697534: Premature GC and invalid lgrp selection with NUMA-aware allocator.
iveresov
parents: 141
diff changeset
859 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
860 st->print(" local/remote/unbiased/uncommitted: %dK/%dK/%dK/%dK, large/small pages: %d/%d\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
861 ls->space_stats()->_local_space / K,
a61af66fc99e Initial load
duke
parents:
diff changeset
862 ls->space_stats()->_remote_space / K,
a61af66fc99e Initial load
duke
parents:
diff changeset
863 ls->space_stats()->_unbiased_space / K,
a61af66fc99e Initial load
duke
parents:
diff changeset
864 ls->space_stats()->_uncommited_space / K,
a61af66fc99e Initial load
duke
parents:
diff changeset
865 ls->space_stats()->_large_pages,
a61af66fc99e Initial load
duke
parents:
diff changeset
866 ls->space_stats()->_small_pages);
a61af66fc99e Initial load
duke
parents:
diff changeset
867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
868 }
a61af66fc99e Initial load
duke
parents:
diff changeset
869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
870
190
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
871 void MutableNUMASpace::verify(bool allow_dirty) {
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
872 // This can be called after setting an arbitary value to the space's top,
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
873 // so an object can cross the chunk boundary. We ensure the parsablity
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
874 // of the space and just walk the objects in linear fashion.
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
875 ensure_parsability();
d1635bf93939 6711930: NUMA allocator: ParOld can create a hole less than minimal object size in the lgrp chunk
iveresov
parents: 144
diff changeset
876 MutableSpace::verify(allow_dirty);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
877 }
a61af66fc99e Initial load
duke
parents:
diff changeset
878
a61af66fc99e Initial load
duke
parents:
diff changeset
879 // Scan pages and gather stats about page placement and size.
a61af66fc99e Initial load
duke
parents:
diff changeset
880 void MutableNUMASpace::LGRPSpace::accumulate_statistics(size_t page_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
881 clear_space_stats();
a61af66fc99e Initial load
duke
parents:
diff changeset
882 char *start = (char*)round_to((intptr_t) space()->bottom(), page_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
883 char* end = (char*)round_down((intptr_t) space()->end(), page_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
884 if (start < end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
885 for (char *p = start; p < end;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
886 os::page_info info;
a61af66fc99e Initial load
duke
parents:
diff changeset
887 if (os::get_page_info(p, &info)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
888 if (info.size > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
889 if (info.size > (size_t)os::vm_page_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
890 space_stats()->_large_pages++;
a61af66fc99e Initial load
duke
parents:
diff changeset
891 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
892 space_stats()->_small_pages++;
a61af66fc99e Initial load
duke
parents:
diff changeset
893 }
a61af66fc99e Initial load
duke
parents:
diff changeset
894 if (info.lgrp_id == lgrp_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
895 space_stats()->_local_space += info.size;
a61af66fc99e Initial load
duke
parents:
diff changeset
896 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
897 space_stats()->_remote_space += info.size;
a61af66fc99e Initial load
duke
parents:
diff changeset
898 }
a61af66fc99e Initial load
duke
parents:
diff changeset
899 p += info.size;
a61af66fc99e Initial load
duke
parents:
diff changeset
900 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
901 p += os::vm_page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
902 space_stats()->_uncommited_space += os::vm_page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
903 }
a61af66fc99e Initial load
duke
parents:
diff changeset
904 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
905 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
908 }
a61af66fc99e Initial load
duke
parents:
diff changeset
909 space_stats()->_unbiased_space = pointer_delta(start, space()->bottom(), sizeof(char)) +
a61af66fc99e Initial load
duke
parents:
diff changeset
910 pointer_delta(space()->end(), end, sizeof(char));
a61af66fc99e Initial load
duke
parents:
diff changeset
911
a61af66fc99e Initial load
duke
parents:
diff changeset
912 }
a61af66fc99e Initial load
duke
parents:
diff changeset
913
a61af66fc99e Initial load
duke
parents:
diff changeset
914 // Scan page_count pages and verify if they have the right size and right placement.
a61af66fc99e Initial load
duke
parents:
diff changeset
915 // If invalid pages are found they are freed in hope that subsequent reallocation
a61af66fc99e Initial load
duke
parents:
diff changeset
916 // will be more successful.
a61af66fc99e Initial load
duke
parents:
diff changeset
917 void MutableNUMASpace::LGRPSpace::scan_pages(size_t page_size, size_t page_count)
a61af66fc99e Initial load
duke
parents:
diff changeset
918 {
a61af66fc99e Initial load
duke
parents:
diff changeset
919 char* range_start = (char*)round_to((intptr_t) space()->bottom(), page_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
920 char* range_end = (char*)round_down((intptr_t) space()->end(), page_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
921
a61af66fc99e Initial load
duke
parents:
diff changeset
922 if (range_start > last_page_scanned() || last_page_scanned() >= range_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
923 set_last_page_scanned(range_start);
a61af66fc99e Initial load
duke
parents:
diff changeset
924 }
a61af66fc99e Initial load
duke
parents:
diff changeset
925
a61af66fc99e Initial load
duke
parents:
diff changeset
926 char *scan_start = last_page_scanned();
a61af66fc99e Initial load
duke
parents:
diff changeset
927 char* scan_end = MIN2(scan_start + page_size * page_count, range_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
928
a61af66fc99e Initial load
duke
parents:
diff changeset
929 os::page_info page_expected, page_found;
a61af66fc99e Initial load
duke
parents:
diff changeset
930 page_expected.size = page_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
931 page_expected.lgrp_id = lgrp_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
932
a61af66fc99e Initial load
duke
parents:
diff changeset
933 char *s = scan_start;
a61af66fc99e Initial load
duke
parents:
diff changeset
934 while (s < scan_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
935 char *e = os::scan_pages(s, (char*)scan_end, &page_expected, &page_found);
a61af66fc99e Initial load
duke
parents:
diff changeset
936 if (e == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
937 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
939 if (e != scan_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
940 if ((page_expected.size != page_size || page_expected.lgrp_id != lgrp_id())
a61af66fc99e Initial load
duke
parents:
diff changeset
941 && page_expected.size != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
942 os::free_memory(s, pointer_delta(e, s, sizeof(char)));
a61af66fc99e Initial load
duke
parents:
diff changeset
943 }
a61af66fc99e Initial load
duke
parents:
diff changeset
944 page_expected = page_found;
a61af66fc99e Initial load
duke
parents:
diff changeset
945 }
a61af66fc99e Initial load
duke
parents:
diff changeset
946 s = e;
a61af66fc99e Initial load
duke
parents:
diff changeset
947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
948
a61af66fc99e Initial load
duke
parents:
diff changeset
949 set_last_page_scanned(scan_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
950 }