Mercurial > hg > truffle
annotate src/share/vm/prims/jvmtiRawMonitor.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | ce8f6bb717c9 |
children |
rev | line source |
---|---|
1878 | 1 /* |
6842
b9a9ed0f8eeb
7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents:
6197
diff
changeset
|
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
1878 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 * | |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "prims/jvmtiRawMonitor.hpp" | |
27 #include "runtime/interfaceSupport.hpp" | |
20197
ce8f6bb717c9
8042195: Introduce umbrella header orderAccess.inline.hpp.
goetz
parents:
6842
diff
changeset
|
28 #include "runtime/orderAccess.inline.hpp" |
ce8f6bb717c9
8042195: Introduce umbrella header orderAccess.inline.hpp.
goetz
parents:
6842
diff
changeset
|
29 #include "runtime/thread.inline.hpp" |
1878 | 30 |
6197 | 31 GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1,true); |
1878 | 32 |
33 void JvmtiPendingMonitors::transition_raw_monitors() { | |
34 assert((Threads::number_of_threads()==1), | |
35 "Java thread has not created yet or more than one java thread \ | |
36 is running. Raw monitor transition will not work"); | |
37 JavaThread *current_java_thread = JavaThread::current(); | |
38 assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm"); | |
39 { | |
40 ThreadBlockInVM __tbivm(current_java_thread); | |
41 for(int i=0; i< count(); i++) { | |
42 JvmtiRawMonitor *rmonitor = monitors()->at(i); | |
43 int r = rmonitor->raw_enter(current_java_thread); | |
44 assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked"); | |
45 } | |
46 } | |
47 // pending monitors are converted to real monitor so delete them all. | |
48 dispose(); | |
49 } | |
50 | |
51 // | |
52 // class JvmtiRawMonitor | |
53 // | |
54 | |
55 JvmtiRawMonitor::JvmtiRawMonitor(const char *name) { | |
56 #ifdef ASSERT | |
6197 | 57 _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal), name); |
1878 | 58 #else |
59 _name = NULL; | |
60 #endif | |
61 _magic = JVMTI_RM_MAGIC; | |
62 } | |
63 | |
64 JvmtiRawMonitor::~JvmtiRawMonitor() { | |
65 #ifdef ASSERT | |
66 FreeHeap(_name); | |
67 #endif | |
68 _magic = 0; | |
69 } | |
70 | |
71 | |
72 bool | |
73 JvmtiRawMonitor::is_valid() { | |
74 int value = 0; | |
75 | |
76 // This object might not be a JvmtiRawMonitor so we can't assume | |
77 // the _magic field is properly aligned. Get the value in a safe | |
78 // way and then check against JVMTI_RM_MAGIC. | |
79 | |
80 switch (sizeof(_magic)) { | |
81 case 2: | |
82 value = Bytes::get_native_u2((address)&_magic); | |
83 break; | |
84 | |
85 case 4: | |
86 value = Bytes::get_native_u4((address)&_magic); | |
87 break; | |
88 | |
89 case 8: | |
90 value = Bytes::get_native_u8((address)&_magic); | |
91 break; | |
92 | |
93 default: | |
94 guarantee(false, "_magic field is an unexpected size"); | |
95 } | |
96 | |
97 return value == JVMTI_RM_MAGIC; | |
98 } | |
99 | |
100 // ------------------------------------------------------------------------- | |
101 // The raw monitor subsystem is entirely distinct from normal | |
102 // java-synchronization or jni-synchronization. raw monitors are not | |
103 // associated with objects. They can be implemented in any manner | |
104 // that makes sense. The original implementors decided to piggy-back | |
105 // the raw-monitor implementation on the existing Java objectMonitor mechanism. | |
106 // This flaw needs to fixed. We should reimplement raw monitors as sui-generis. | |
107 // Specifically, we should not implement raw monitors via java monitors. | |
108 // Time permitting, we should disentangle and deconvolve the two implementations | |
109 // and move the resulting raw monitor implementation over to the JVMTI directories. | |
110 // Ideally, the raw monitor implementation would be built on top of | |
111 // park-unpark and nothing else. | |
112 // | |
113 // raw monitors are used mainly by JVMTI | |
114 // The raw monitor implementation borrows the ObjectMonitor structure, | |
115 // but the operators are degenerate and extremely simple. | |
116 // | |
117 // Mixed use of a single objectMonitor instance -- as both a raw monitor | |
118 // and a normal java monitor -- is not permissible. | |
119 // | |
120 // Note that we use the single RawMonitor_lock to protect queue operations for | |
121 // _all_ raw monitors. This is a scalability impediment, but since raw monitor usage | |
122 // is deprecated and rare, this is not of concern. The RawMonitor_lock can not | |
123 // be held indefinitely. The critical sections must be short and bounded. | |
124 // | |
125 // ------------------------------------------------------------------------- | |
126 | |
127 int JvmtiRawMonitor::SimpleEnter (Thread * Self) { | |
128 for (;;) { | |
129 if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) { | |
130 return OS_OK ; | |
131 } | |
132 | |
133 ObjectWaiter Node (Self) ; | |
134 Self->_ParkEvent->reset() ; // strictly optional | |
135 Node.TState = ObjectWaiter::TS_ENTER ; | |
136 | |
137 RawMonitor_lock->lock_without_safepoint_check() ; | |
138 Node._next = _EntryList ; | |
139 _EntryList = &Node ; | |
140 OrderAccess::fence() ; | |
141 if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) { | |
142 _EntryList = Node._next ; | |
143 RawMonitor_lock->unlock() ; | |
144 return OS_OK ; | |
145 } | |
146 RawMonitor_lock->unlock() ; | |
147 while (Node.TState == ObjectWaiter::TS_ENTER) { | |
148 Self->_ParkEvent->park() ; | |
149 } | |
150 } | |
151 } | |
152 | |
153 int JvmtiRawMonitor::SimpleExit (Thread * Self) { | |
154 guarantee (_owner == Self, "invariant") ; | |
155 OrderAccess::release_store_ptr (&_owner, NULL) ; | |
156 OrderAccess::fence() ; | |
157 if (_EntryList == NULL) return OS_OK ; | |
158 ObjectWaiter * w ; | |
159 | |
160 RawMonitor_lock->lock_without_safepoint_check() ; | |
161 w = _EntryList ; | |
162 if (w != NULL) { | |
163 _EntryList = w->_next ; | |
164 } | |
165 RawMonitor_lock->unlock() ; | |
166 if (w != NULL) { | |
167 guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ; | |
168 ParkEvent * ev = w->_event ; | |
169 w->TState = ObjectWaiter::TS_RUN ; | |
170 OrderAccess::fence() ; | |
171 ev->unpark() ; | |
172 } | |
173 return OS_OK ; | |
174 } | |
175 | |
176 int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) { | |
177 guarantee (_owner == Self , "invariant") ; | |
178 guarantee (_recursions == 0, "invariant") ; | |
179 | |
180 ObjectWaiter Node (Self) ; | |
181 Node._notified = 0 ; | |
182 Node.TState = ObjectWaiter::TS_WAIT ; | |
183 | |
184 RawMonitor_lock->lock_without_safepoint_check() ; | |
185 Node._next = _WaitSet ; | |
186 _WaitSet = &Node ; | |
187 RawMonitor_lock->unlock() ; | |
188 | |
189 SimpleExit (Self) ; | |
190 guarantee (_owner != Self, "invariant") ; | |
191 | |
192 int ret = OS_OK ; | |
193 if (millis <= 0) { | |
194 Self->_ParkEvent->park(); | |
195 } else { | |
196 ret = Self->_ParkEvent->park(millis); | |
197 } | |
198 | |
199 // If thread still resides on the waitset then unlink it. | |
200 // Double-checked locking -- the usage is safe in this context | |
201 // as we TState is volatile and the lock-unlock operators are | |
202 // serializing (barrier-equivalent). | |
203 | |
204 if (Node.TState == ObjectWaiter::TS_WAIT) { | |
205 RawMonitor_lock->lock_without_safepoint_check() ; | |
206 if (Node.TState == ObjectWaiter::TS_WAIT) { | |
207 // Simple O(n) unlink, but performance isn't critical here. | |
208 ObjectWaiter * p ; | |
209 ObjectWaiter * q = NULL ; | |
210 for (p = _WaitSet ; p != &Node; p = p->_next) { | |
211 q = p ; | |
212 } | |
213 guarantee (p == &Node, "invariant") ; | |
214 if (q == NULL) { | |
215 guarantee (p == _WaitSet, "invariant") ; | |
216 _WaitSet = p->_next ; | |
217 } else { | |
218 guarantee (p == q->_next, "invariant") ; | |
219 q->_next = p->_next ; | |
220 } | |
221 Node.TState = ObjectWaiter::TS_RUN ; | |
222 } | |
223 RawMonitor_lock->unlock() ; | |
224 } | |
225 | |
226 guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ; | |
227 SimpleEnter (Self) ; | |
228 | |
229 guarantee (_owner == Self, "invariant") ; | |
230 guarantee (_recursions == 0, "invariant") ; | |
231 return ret ; | |
232 } | |
233 | |
234 int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) { | |
235 guarantee (_owner == Self, "invariant") ; | |
236 if (_WaitSet == NULL) return OS_OK ; | |
237 | |
238 // We have two options: | |
239 // A. Transfer the threads from the WaitSet to the EntryList | |
240 // B. Remove the thread from the WaitSet and unpark() it. | |
241 // | |
242 // We use (B), which is crude and results in lots of futile | |
243 // context switching. In particular (B) induces lots of contention. | |
244 | |
245 ParkEvent * ev = NULL ; // consider using a small auto array ... | |
246 RawMonitor_lock->lock_without_safepoint_check() ; | |
247 for (;;) { | |
248 ObjectWaiter * w = _WaitSet ; | |
249 if (w == NULL) break ; | |
250 _WaitSet = w->_next ; | |
251 if (ev != NULL) { ev->unpark(); ev = NULL; } | |
252 ev = w->_event ; | |
253 OrderAccess::loadstore() ; | |
254 w->TState = ObjectWaiter::TS_RUN ; | |
255 OrderAccess::storeload(); | |
256 if (!All) break ; | |
257 } | |
258 RawMonitor_lock->unlock() ; | |
259 if (ev != NULL) ev->unpark(); | |
260 return OS_OK ; | |
261 } | |
262 | |
263 // Any JavaThread will enter here with state _thread_blocked | |
264 int JvmtiRawMonitor::raw_enter(TRAPS) { | |
265 TEVENT (raw_enter) ; | |
266 void * Contended ; | |
267 | |
268 // don't enter raw monitor if thread is being externally suspended, it will | |
269 // surprise the suspender if a "suspended" thread can still enter monitor | |
270 JavaThread * jt = (JavaThread *)THREAD; | |
271 if (THREAD->is_Java_thread()) { | |
272 jt->SR_lock()->lock_without_safepoint_check(); | |
273 while (jt->is_external_suspend()) { | |
274 jt->SR_lock()->unlock(); | |
275 jt->java_suspend_self(); | |
276 jt->SR_lock()->lock_without_safepoint_check(); | |
277 } | |
278 // guarded by SR_lock to avoid racing with new external suspend requests. | |
279 Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ; | |
280 jt->SR_lock()->unlock(); | |
281 } else { | |
282 Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ; | |
283 } | |
284 | |
285 if (Contended == THREAD) { | |
286 _recursions ++ ; | |
287 return OM_OK ; | |
288 } | |
289 | |
290 if (Contended == NULL) { | |
291 guarantee (_owner == THREAD, "invariant") ; | |
292 guarantee (_recursions == 0, "invariant") ; | |
293 return OM_OK ; | |
294 } | |
295 | |
296 THREAD->set_current_pending_monitor(this); | |
297 | |
298 if (!THREAD->is_Java_thread()) { | |
299 // No other non-Java threads besides VM thread would acquire | |
300 // a raw monitor. | |
301 assert(THREAD->is_VM_thread(), "must be VM thread"); | |
302 SimpleEnter (THREAD) ; | |
303 } else { | |
304 guarantee (jt->thread_state() == _thread_blocked, "invariant") ; | |
305 for (;;) { | |
306 jt->set_suspend_equivalent(); | |
307 // cleared by handle_special_suspend_equivalent_condition() or | |
308 // java_suspend_self() | |
309 SimpleEnter (THREAD) ; | |
310 | |
311 // were we externally suspended while we were waiting? | |
312 if (!jt->handle_special_suspend_equivalent_condition()) break ; | |
313 | |
314 // This thread was externally suspended | |
315 // | |
316 // This logic isn't needed for JVMTI raw monitors, | |
317 // but doesn't hurt just in case the suspend rules change. This | |
318 // logic is needed for the JvmtiRawMonitor.wait() reentry phase. | |
319 // We have reentered the contended monitor, but while we were | |
320 // waiting another thread suspended us. We don't want to reenter | |
321 // the monitor while suspended because that would surprise the | |
322 // thread that suspended us. | |
323 // | |
324 // Drop the lock - | |
325 SimpleExit (THREAD) ; | |
326 | |
327 jt->java_suspend_self(); | |
328 } | |
329 | |
330 assert(_owner == THREAD, "Fatal error with monitor owner!"); | |
331 assert(_recursions == 0, "Fatal error with monitor recursions!"); | |
332 } | |
333 | |
334 THREAD->set_current_pending_monitor(NULL); | |
335 guarantee (_recursions == 0, "invariant") ; | |
336 return OM_OK; | |
337 } | |
338 | |
339 // Used mainly for JVMTI raw monitor implementation | |
340 // Also used for JvmtiRawMonitor::wait(). | |
341 int JvmtiRawMonitor::raw_exit(TRAPS) { | |
342 TEVENT (raw_exit) ; | |
343 if (THREAD != _owner) { | |
344 return OM_ILLEGAL_MONITOR_STATE; | |
345 } | |
346 if (_recursions > 0) { | |
347 --_recursions ; | |
348 return OM_OK ; | |
349 } | |
350 | |
351 void * List = _EntryList ; | |
352 SimpleExit (THREAD) ; | |
353 | |
354 return OM_OK; | |
355 } | |
356 | |
357 // Used for JVMTI raw monitor implementation. | |
358 // All JavaThreads will enter here with state _thread_blocked | |
359 | |
360 int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) { | |
361 TEVENT (raw_wait) ; | |
362 if (THREAD != _owner) { | |
363 return OM_ILLEGAL_MONITOR_STATE; | |
364 } | |
365 | |
366 // To avoid spurious wakeups we reset the parkevent -- This is strictly optional. | |
367 // The caller must be able to tolerate spurious returns from raw_wait(). | |
368 THREAD->_ParkEvent->reset() ; | |
369 OrderAccess::fence() ; | |
370 | |
371 // check interrupt event | |
372 if (interruptible && Thread::is_interrupted(THREAD, true)) { | |
373 return OM_INTERRUPTED; | |
374 } | |
375 | |
376 intptr_t save = _recursions ; | |
377 _recursions = 0 ; | |
378 _waiters ++ ; | |
379 if (THREAD->is_Java_thread()) { | |
380 guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ; | |
381 ((JavaThread *)THREAD)->set_suspend_equivalent(); | |
382 } | |
383 int rv = SimpleWait (THREAD, millis) ; | |
384 _recursions = save ; | |
385 _waiters -- ; | |
386 | |
387 guarantee (THREAD == _owner, "invariant") ; | |
388 if (THREAD->is_Java_thread()) { | |
389 JavaThread * jSelf = (JavaThread *) THREAD ; | |
390 for (;;) { | |
391 if (!jSelf->handle_special_suspend_equivalent_condition()) break ; | |
392 SimpleExit (THREAD) ; | |
393 jSelf->java_suspend_self(); | |
394 SimpleEnter (THREAD) ; | |
395 jSelf->set_suspend_equivalent() ; | |
396 } | |
397 } | |
398 guarantee (THREAD == _owner, "invariant") ; | |
399 | |
400 if (interruptible && Thread::is_interrupted(THREAD, true)) { | |
401 return OM_INTERRUPTED; | |
402 } | |
403 return OM_OK ; | |
404 } | |
405 | |
406 int JvmtiRawMonitor::raw_notify(TRAPS) { | |
407 TEVENT (raw_notify) ; | |
408 if (THREAD != _owner) { | |
409 return OM_ILLEGAL_MONITOR_STATE; | |
410 } | |
411 SimpleNotify (THREAD, false) ; | |
412 return OM_OK; | |
413 } | |
414 | |
415 int JvmtiRawMonitor::raw_notifyAll(TRAPS) { | |
416 TEVENT (raw_notifyAll) ; | |
417 if (THREAD != _owner) { | |
418 return OM_ILLEGAL_MONITOR_STATE; | |
419 } | |
420 SimpleNotify (THREAD, true) ; | |
421 return OM_OK; | |
422 } | |
423 |