Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/shared/concurrentGCThread.cpp @ 10374:87c64c0438fb
6976350: G1: deal with fragmentation while copying objects during GC
Summary: Create G1ParGCAllocBufferContainer to contain two buffers instead of previously using one buffer, in order to hold the first priority buffer longer. Thus, when some large objects hits the value of free space left in the first priority buffer it has an alternative to fit in the second priority buffer while the first priority buffer is given more chances to try allocating smaller objects. Overall, it will improve heap space efficiency.
Reviewed-by: johnc, jmasa, brutisso
Contributed-by: tamao <tao.mao@oracle.com>
author | tamao |
---|---|
date | Mon, 03 Jun 2013 14:37:13 -0700 |
parents | aed758eda82a |
children | 63a4eb8bcd23 581e70386ec9 |
rev | line source |
---|---|
342 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4022
diff
changeset
|
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. |
342 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "gc_implementation/shared/concurrentGCThread.hpp" | |
28 #include "oops/instanceRefKlass.hpp" | |
29 #include "oops/oop.inline.hpp" | |
30 #include "runtime/init.hpp" | |
31 #include "runtime/interfaceSupport.hpp" | |
32 #include "runtime/java.hpp" | |
33 #include "runtime/javaCalls.hpp" | |
342 | 34 |
1972 | 35 // CopyrightVersion 1.2 |
342 | 36 |
37 int ConcurrentGCThread::_CGC_flag = CGC_nil; | |
38 | |
39 SuspendibleThreadSet ConcurrentGCThread::_sts; | |
40 | |
794 | 41 ConcurrentGCThread::ConcurrentGCThread() : |
42 _should_terminate(false), _has_terminated(false) { | |
342 | 43 _sts.initialize(); |
44 }; | |
45 | |
46 void ConcurrentGCThread::safepoint_synchronize() { | |
47 _sts.suspend_all(); | |
48 } | |
49 | |
50 void ConcurrentGCThread::safepoint_desynchronize() { | |
51 _sts.resume_all(); | |
52 } | |
53 | |
54 void ConcurrentGCThread::create_and_start() { | |
55 if (os::create_thread(this, os::cgc_thread)) { | |
56 // XXX: need to set this to low priority | |
57 // unless "agressive mode" set; priority | |
58 // should be just less than that of VMThread. | |
59 os::set_priority(this, NearMaxPriority); | |
60 if (!_should_terminate && !DisableStartThread) { | |
61 os::start_thread(this); | |
62 } | |
63 } | |
64 } | |
65 | |
66 void ConcurrentGCThread::initialize_in_thread() { | |
67 this->record_stack_base_and_size(); | |
68 this->initialize_thread_local_storage(); | |
69 this->set_active_handles(JNIHandleBlock::allocate_block()); | |
70 // From this time Thread::current() should be working. | |
71 assert(this == Thread::current(), "just checking"); | |
72 } | |
73 | |
74 void ConcurrentGCThread::wait_for_universe_init() { | |
75 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); | |
76 while (!is_init_completed() && !_should_terminate) { | |
77 CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200); | |
78 } | |
79 } | |
80 | |
81 void ConcurrentGCThread::terminate() { | |
82 // Signal that it is terminated | |
83 { | |
84 MutexLockerEx mu(Terminator_lock, | |
85 Mutex::_no_safepoint_check_flag); | |
86 _has_terminated = true; | |
87 Terminator_lock->notify(); | |
88 } | |
89 | |
90 // Thread destructor usually does this.. | |
91 ThreadLocalStorage::set_thread(NULL); | |
92 } | |
93 | |
94 | |
95 void SuspendibleThreadSet::initialize_work() { | |
96 MutexLocker x(STS_init_lock); | |
97 if (!_initialized) { | |
98 _m = new Monitor(Mutex::leaf, | |
99 "SuspendibleThreadSetLock", true); | |
100 _async = 0; | |
101 _async_stop = false; | |
102 _async_stopped = 0; | |
103 _initialized = true; | |
104 } | |
105 } | |
106 | |
107 void SuspendibleThreadSet::join() { | |
108 initialize(); | |
109 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); | |
110 while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); | |
111 _async++; | |
112 assert(_async > 0, "Huh."); | |
113 } | |
114 | |
115 void SuspendibleThreadSet::leave() { | |
116 assert(_initialized, "Must be initialized."); | |
117 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); | |
118 _async--; | |
119 assert(_async >= 0, "Huh."); | |
120 if (_async_stop) _m->notify_all(); | |
121 } | |
122 | |
123 void SuspendibleThreadSet::yield(const char* id) { | |
124 assert(_initialized, "Must be initialized."); | |
125 if (_async_stop) { | |
126 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); | |
127 if (_async_stop) { | |
128 _async_stopped++; | |
129 assert(_async_stopped > 0, "Huh."); | |
130 if (_async_stopped == _async) { | |
131 if (ConcGCYieldTimeout > 0) { | |
132 double now = os::elapsedTime(); | |
133 guarantee((now - _suspend_all_start) * 1000.0 < | |
134 (double)ConcGCYieldTimeout, | |
135 "Long delay; whodunit?"); | |
136 } | |
137 } | |
138 _m->notify_all(); | |
139 while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); | |
140 _async_stopped--; | |
141 assert(_async >= 0, "Huh"); | |
142 _m->notify_all(); | |
143 } | |
144 } | |
145 } | |
146 | |
147 void SuspendibleThreadSet::suspend_all() { | |
148 initialize(); // If necessary. | |
149 if (ConcGCYieldTimeout > 0) { | |
150 _suspend_all_start = os::elapsedTime(); | |
151 } | |
152 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); | |
153 assert(!_async_stop, "Only one at a time."); | |
154 _async_stop = true; | |
155 while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag); | |
156 } | |
157 | |
158 void SuspendibleThreadSet::resume_all() { | |
159 assert(_initialized, "Must be initialized."); | |
160 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); | |
161 assert(_async_stopped == _async, "Huh."); | |
162 _async_stop = false; | |
163 _m->notify_all(); | |
164 } | |
165 | |
166 static void _sltLoop(JavaThread* thread, TRAPS) { | |
167 SurrogateLockerThread* slt = (SurrogateLockerThread*)thread; | |
168 slt->loop(); | |
169 } | |
170 | |
171 SurrogateLockerThread::SurrogateLockerThread() : | |
172 JavaThread(&_sltLoop), | |
173 _monitor(Mutex::nonleaf, "SLTMonitor"), | |
174 _buffer(empty) | |
175 {} | |
176 | |
177 SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4022
diff
changeset
|
178 Klass* k = |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
179 SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), |
342 | 180 true, CHECK_NULL); |
181 instanceKlassHandle klass (THREAD, k); | |
182 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL); | |
183 | |
1842
6e0aac35bfa9
6980838: G1: guarantee(false) failed: thread has an unexpected active value in its SATB queue
tonyp
parents:
1552
diff
changeset
|
184 const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)"; |
342 | 185 Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL); |
186 | |
187 // Initialize thread_oop to put it into the system threadGroup | |
188 Handle thread_group (THREAD, Universe::system_thread_group()); | |
189 JavaValue result(T_VOID); | |
190 JavaCalls::call_special(&result, thread_oop, | |
191 klass, | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
192 vmSymbols::object_initializer_name(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
193 vmSymbols::threadgroup_string_void_signature(), |
342 | 194 thread_group, |
195 string, | |
196 CHECK_NULL); | |
197 | |
198 SurrogateLockerThread* res; | |
199 { | |
200 MutexLocker mu(Threads_lock); | |
201 res = new SurrogateLockerThread(); | |
202 | |
203 // At this point it may be possible that no osthread was created for the | |
204 // JavaThread due to lack of memory. We would have to throw an exception | |
205 // in that case. However, since this must work and we do not allow | |
206 // exceptions anyway, check and abort if this fails. | |
207 if (res == NULL || res->osthread() == NULL) { | |
208 vm_exit_during_initialization("java.lang.OutOfMemoryError", | |
209 "unable to create new native thread"); | |
210 } | |
211 java_lang_Thread::set_thread(thread_oop(), res); | |
212 java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); | |
213 java_lang_Thread::set_daemon(thread_oop()); | |
214 | |
215 res->set_threadObj(thread_oop()); | |
216 Threads::add(res); | |
217 Thread::start(res); | |
218 } | |
219 os::yield(); // This seems to help with initial start-up of SLT | |
220 return res; | |
221 } | |
222 | |
223 void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) { | |
224 MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); | |
225 assert(_buffer == empty, "Should be empty"); | |
226 assert(msg != empty, "empty message"); | |
4022
db89aa49298f
7099824: G1: we should take the pending list lock before doing the remark pause
johnc
parents:
3767
diff
changeset
|
227 assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread"); |
db89aa49298f
7099824: G1: we should take the pending list lock before doing the remark pause
johnc
parents:
3767
diff
changeset
|
228 |
342 | 229 _buffer = msg; |
230 while (_buffer != empty) { | |
231 _monitor.notify(); | |
232 _monitor.wait(Mutex::_no_safepoint_check_flag); | |
233 } | |
234 } | |
235 | |
236 // ======= Surrogate Locker Thread ============= | |
237 | |
238 void SurrogateLockerThread::loop() { | |
239 BasicLock pll_basic_lock; | |
240 SLT_msg_type msg; | |
241 debug_only(unsigned int owned = 0;) | |
242 | |
243 while (/* !isTerminated() */ 1) { | |
244 { | |
245 MutexLocker x(&_monitor); | |
246 // Since we are a JavaThread, we can't be here at a safepoint. | |
247 assert(!SafepointSynchronize::is_at_safepoint(), | |
248 "SLT is a JavaThread"); | |
249 // wait for msg buffer to become non-empty | |
250 while (_buffer == empty) { | |
251 _monitor.notify(); | |
252 _monitor.wait(); | |
253 } | |
254 msg = _buffer; | |
255 } | |
256 switch(msg) { | |
257 case acquirePLL: { | |
6735
aed758eda82a
7195833: NPG: Rename instanceClassLoaderKlass, instanceRefKlass and instanceMirrorKlass
coleenp
parents:
6725
diff
changeset
|
258 InstanceRefKlass::acquire_pending_list_lock(&pll_basic_lock); |
342 | 259 debug_only(owned++;) |
260 break; | |
261 } | |
262 case releaseAndNotifyPLL: { | |
263 assert(owned > 0, "Don't have PLL"); | |
6735
aed758eda82a
7195833: NPG: Rename instanceClassLoaderKlass, instanceRefKlass and instanceMirrorKlass
coleenp
parents:
6725
diff
changeset
|
264 InstanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock); |
342 | 265 debug_only(owned--;) |
266 break; | |
267 } | |
268 case empty: | |
269 default: { | |
270 guarantee(false,"Unexpected message in _buffer"); | |
271 break; | |
272 } | |
273 } | |
274 { | |
275 MutexLocker x(&_monitor); | |
276 // Since we are a JavaThread, we can't be here at a safepoint. | |
277 assert(!SafepointSynchronize::is_at_safepoint(), | |
278 "SLT is a JavaThread"); | |
279 _buffer = empty; | |
280 _monitor.notify(); | |
281 } | |
282 } | |
283 assert(!_monitor.owned_by_self(), "Should unlock before exit."); | |
284 } | |
285 | |
286 | |
287 // ===== STS Access From Outside CGCT ===== | |
288 | |
289 void ConcurrentGCThread::stsYield(const char* id) { | |
290 assert( Thread::current()->is_ConcurrentGC_thread(), | |
291 "only a conc GC thread can call this" ); | |
292 _sts.yield(id); | |
293 } | |
294 | |
295 bool ConcurrentGCThread::stsShouldYield() { | |
296 assert( Thread::current()->is_ConcurrentGC_thread(), | |
297 "only a conc GC thread can call this" ); | |
298 return _sts.should_yield(); | |
299 } | |
300 | |
301 void ConcurrentGCThread::stsJoin() { | |
302 assert( Thread::current()->is_ConcurrentGC_thread(), | |
303 "only a conc GC thread can call this" ); | |
304 _sts.join(); | |
305 } | |
306 | |
307 void ConcurrentGCThread::stsLeave() { | |
308 assert( Thread::current()->is_ConcurrentGC_thread(), | |
309 "only a conc GC thread can call this" ); | |
310 _sts.leave(); | |
311 } |